package com.share.example.classload.config;

import com.share.common.utils.AlphaUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;

/**
 * 提供一个方法---操作者输入对应类全路径或者对应的接口全路径
 */
@Slf4j
@Component
public class ServiceImplRegistry implements BeanDefinitionRegistryPostProcessor {

    private BeanDefinitionRegistry registry;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        log.info("正在初始化registry对象");
        this.registry = registry;
    }

    /**
     * 根据包路径获取包及子包下的所有类
     */
    public Class registerBean(Class implClass, Class interfaceClass) {
        try {
            //接口类定义
            GenericBeanDefinition definition = (GenericBeanDefinition) BeanDefinitionBuilder.genericBeanDefinition(interfaceClass).getRawBeanDefinition();

            // 代理实现类,或者实现类
            definition.setBeanClass(implClass);

            //设置注入类型
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);

            String beanName = AlphaUtil.firstCharToLow(interfaceClass.getSimpleName());
            registry.registerBeanDefinition(beanName, definition);//getbean是这里第一个参数决定的

            //返回实现类吧
            return definition.getBeanClass();
        } catch (Exception e) {
            log.error("bean注入异常", e);
            return null;
        }
    }

    /**
     * @param implClassPath      "com.share.UserServiceImpl"
     * @param interfaceClassPath "com.share.UserService"
     * @return
     */
    public Class registerBean(String implClassPath, String interfaceClassPath) {
        try {
            Class<?> interfaceClass = Class.forName(interfaceClassPath);
            Class<?> implClass = Class.forName(implClassPath);
            return registerBean(implClass, interfaceClass);
        } catch (Exception e) {
            log.error("bean注入异常", e);
            return null;
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }
}
